/*****************************************************************************
 * Copyright (C) Marcelo F. Ochoa. All rights reserved.                      *
 * ------------------------------------------------------------------------- *
 * This software is published under the terms of the Apache Software License *
 * version 1.1, a copy of which has been included  with this distribution in *
 * the LICENSE file.                                                         *
 *****************************************************************************/

package com.prism.toolkit;


import java.sql.Connection;
import java.sql.ResultSet;

import java.sql.Statement;

import java.text.DateFormat;

import java.text.SimpleDateFormat;

import oracle.jdbc.driver.OracleDriver;

import oracle.sql.BLOB;
import oracle.sql.CLOB;

import oracle.xdb.XMLType;

/**
  * Upload/Download functionality for Oracle Lite/8i-10g Java
  */
public class JwpgDocLoad {
    private static BLOB blobLocator = null;

    private static CLOB clobLocator = null;

    private static String fileName = null;

    private static boolean cachingContent = false;

    private static XMLType xmlLocator = null;

    /**
     * This should be called from within a document download procedure
     * to signal the DBPrism Gateway that filename is to be downloaded
     * from the document table to the client's browser.
     * Normally, a document will be downloaded to the browser unless the
     * browser sends an 'If-Modified-Since' header to the gateway indicating
     * that it has the requested document in its cache.  In that case,
     * the gateway will determine if the browser's cached copy is up to date,
     * and if it is, it will send a 302 message to the browser indicating
     * that the browser should display the cached copy.  However, because
     * a document URL and a document do not necessarily have a one-to-one
     * relationship in the DBPrism Web Gateway, in some cases it may be
     * undesirable to have the cached copy of a document displayed.  In those
     * cases, the p_bcaching parameter should be set to TRUE to indicate to
     * the gateway to ignore the 'If-Modified-Since' header, and download the
     * document.
     * PARAMS:
     *   @param filename  : file to download from the document table.
     *   @param caching   : browser caching enabled?
     */
    public static void DOWNLOADFILE(String filename, boolean caching) {
        fileName = filename;
        cachingContent = caching;
        blobLocator = null;
        clobLocator = null;
        xmlLocator = null;
    }

    /**
     * set the file download functionality
     * @param filename to download from DAD's DOCUMENT_TABLE parameter
     */
    public static void DOWNLOADFILE(String filename) {
        DOWNLOADFILE(filename, true);
    }

    /**
     * set a BLOB object as download information
     * @param locator to the BLOB to be downloaded
     */
    public static void DOWNLOADFILE(BLOB locator) {
        fileName = null;
        cachingContent = true;
        blobLocator = locator;
        clobLocator = null;
        xmlLocator = null;
    }

    /**
     * set a CLOB object as download information
     * @param locator to the CLOB to be downloaded
     */
    public static void DOWNLOADFILE(CLOB locator) {
        fileName = null;
        cachingContent = true;
        blobLocator = null;
        clobLocator = locator;
        xmlLocator = null;
    }

    /**
     * set an XMLType object as output information
     * @param xmlOutput object with the XML to be returned
     */
    public static void DOWNLOADFILE(XMLType xmlOutput) {
        fileName = null;
        cachingContent = true;
        blobLocator = null;
        clobLocator = null;
        xmlLocator = xmlOutput;
    }

    /**
     * @return 1 if there is download information, otherwise 0
     */
    public static int ISFILEDOWNLOAD() {
        if (fileName != null || blobLocator != null || clobLocator != null|| xmlLocator != null)
            return 1;
        else
            return 0;
    }

    /**
     * Private file upload/download procedures and functions
     *
     * **WARNING**
     * The following procedures are used internally by the
     * DBPrism Gateway.  Do not call them from your Java code.
     *
     *   Get the name of the file to be downloaded
     * RETURNS:
     *  docInfo       encoded document information
     * B - Blob
     * C - Clob
     * X - XMLType
     * nnXfilename
     * 12XNOT_MODIFIED, if not reload required
     * Error: msg, if there are errors
     * @return an encoded string information about DBPrism Java Download information
     * @see com.prism.oracle.DownloadJava
     */
    public static String GETDOWNLOADFILE() {
        Connection sqlconn = null;
        String docTable = null;
        java.util.Date lastClientMod = null;
        try {
            sqlconn = (new OracleDriver()).defaultConnection();
        } catch (Exception e) {
            return "Error: Can't get Default Connection:\n" + e.getMessage();
        }
        try {
            ResultSet rset = null;
            Statement stmt = null;
            if (fileName != null) {
                try {
                    docTable = Jowa.GETCGIVAR("DOCUMENT_TABLE");
                    if (docTable == null)
                        return "Error: can't get CGI var DOCUMENT_TABLE";
                } catch (Exception e) {
                    return "Error: can't get CGI var DOCUMENT_TABLE";
                }
                String lastMod = Jowa.GETCGIVAR("HTTP_IF_MODIFIED_SINCE");
                // Convert the Date especification to Age format of Servlets Cookie
                // Acording to non deprected api of JDK 1.1
                if (cachingContent && lastMod != null) {
                    try {
                        DateFormat df =
                            new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss",
                                                             java.util.Locale
                                                             .US);
                        lastClientMod = df.parse(lastMod);
                    } catch (Exception e) {
                        return "Error: can't parse If-Modified-Since header '" +
                        lastMod + "'\n" + e.getMessage();
                    }
                    try {
                        // Create a Statement
                        stmt = sqlconn.createStatement();
                        // Select the lobs
                        rset =
                            stmt.executeQuery("select last_updated from " + docTable +
                                                 " where name = '" + fileName +
                                                 "'");
                        if (rset.next()) {
                            java.sql.Date lastDbMod = rset.getDate(1);
                            rset.close();
                            stmt.close();
                            // Round date to second before comparing
                            if ((lastDbMod.getTime() / 1000 * 1000) ==
                                (lastClientMod.getTime() / 1000 * 1000))
                                return fileName.length() + "X" + fileName +
                                "12XNOT_MODIFIED";
                        }
                    } catch (Exception e) {
                        return "Error: can't get last_updated from table '" +
                        docTable + "'\n" + e.getMessage();
                    }
                }
                return fileName.length() + "X" + fileName;
            } else 
                return (clobLocator!=null) ? "C" : (blobLocator!=null) ? "B" : "X";
        } catch (Exception e) {
            return "Error: internal error:\n" + e.getMessage();
        }
    }

    /**
     * @return BLOB to be download
     */
    public static BLOB GETDOWNLOADBLOB() {
        return blobLocator;
    }

    /**
     * @return CLOB to be downloaded
     */
    public static CLOB GETDOWNLOADCLOB() {
        return clobLocator;
    }

    /**
     * @return XMLType to be download
     */
    public static XMLType GETDOWNLOADXML() {
        return xmlLocator;
    }

    /**
     * Return the length of a lob to be downloaded.  This is only called
     * when the user hasn't already specified a predetermined content-length.
     * @return BLOB/CLOB/XMLType length
     */
    public static long GETCONTENTLENGTH() {
        try {
            long length = (blobLocator != null) ? blobLocator.length() : 
                   (clobLocator != null) ? clobLocator.length() : 
                   (xmlLocator != null) ? xmlLocator.getLength() : 0;
            return length;
        } catch (Exception e) {
            return 0;
        }
    }
}
